For a "native" way on Istio to do what you want you will have to wait. Envoy team added custom error responses as a 1.9.0 release milestone. Hopefully, they will include it on the release and we will get it by the end of the year. So we will be able to use it on Istio.
https://github.com/envoyproxy/envoy/issues/1178
About custom approaches, you could use you can put a nginx (In the same pod) serving those custom error pages in front of any user facing app. You won't be able to change some errors like 503 or 404 given by Envoy proxy itself though.
(not working yet, see below) Another approach if you need to customize errors given by Envoy as well, would be using nginx-ingress-controller, which can serve the custom error pages, together with Istio. If you want to try, have a look at this issue and the one they reference on the first comment, it can be helpful.
https://github.com/kubernetes/ingress-nginx/issues/2126
Update 21st Nov 2018
For this approach to work, you're going to have to wait as well. (probably more than with envoy) I tested it myself and I was facing an issue that nginx has to solve in order to get this working. When you define a default backend, nginx get the endpoints (ip:port) from the kubernetes service directly and then tries to access to those IPs on the cluster. Instead of accessing through the name and letting Istio route that connection, that it is how is meant to work.
Have a look at this https://github.com/kubernetes/ingress-nginx/issues/2318