It doesn't "silently mangle" binary data - it assumes you're piping PS objects or text streams through. If it is a text stream, then it will pipe through as Unicode by default.
Invoke-WebRequest (curl) pipes out an object, with the content in (object).Content. Using | uses Unicode by default which "mangles" binary output. So it tries to convert the object into a Unicode text stream then into the file.
The correct way to save an image would be to simply set -OutFile (-o) in Invoke-WebRequest.
If you MUST pipe it through, then you need to access the object's .Content, then use Set-Content -AsByteStream (for PS7+) or use Set-Content -Encoding byte (PS5)
PS5> $(Invoke-WebRequest -Uri https://www.w3schools.com/html/w3schools.jpg -ContentType 'image/jpg').Content | Set-Content -Encoding byte test.jpg
PS7> $(Invoke-WebRequest -Uri https://www.w3schools.com/html/w3schools.jpg -ContentType 'image/jpg').Content | Set-Content -AsByteStream test.jpg
This is useful if you wanted to put the image inside a variable (rather than create a temporary file for the image) and pass it around until you figure out what you want to do with it.