Here is the my final solution after the leads from other answers here. I use the media:request event along with the lesser known AddOnSendingHeaders method on Request object that basically gives me a final chance to change headers before IIS sends the request to the client.

    public class ChangeFileName
    {
        public void OnMediaRequest(object sender, EventArgs args)
        {
            SitecoreEventArgs eventArgs = args as SitecoreEventArgs;

            MediaRequest mediaRequest = eventArgs?.Parameters?[0] as MediaRequest;


            if (mediaRequest == null)
            {
                return;
            }

            MediaItem mediaItem = MediaManager.GetMedia(mediaRequest.MediaUri).MediaData.MediaItem;

            if(mediaItem == null)
            {
                return;
            }

            HttpRequest request = mediaRequest.InnerRequest;

            request.RequestContext.HttpContext.Response.AddOnSendingHeaders(context =>
            {
                if (CheckFileType(mediaItem))
                    context.Response.Headers["Content-Disposition"] = FixFileName(context.Response.Headers["Content-Disposition"]));
            });
        }

    }

Then of course, I had to add the event handler to the config:

    <event name="media:request">
            <handler type="MyAssembly.ChangeFileName, MyAssembly" method="OnMediaRequest"/>
          </event>