Monkey patching is done by Zone.js. In ng_zone.ts, zone.ts is loaded which creates the root zone as well as monkey patches the API.
NGZone simply forks a child zone named 'angular' and provides callbacks in zone specifications. In those callbacks, it emits events which are further subscribed in application_ref.ts and change detection is kicked off.
Monkey Patching: This is done by calling Zone.__load_patch() function with 2 arguments. First argument is the identifier of the monkey-patched APIs and second is the patch function which when executed, replaces the actual browser API with the re-defined version.
Now, this is just the tip of the iceberg. Actual magic is done by calling patchMethod() of utils.ts. For set/clearTimeOut case, this is done here.
In patchMethod(), original api is saved in local variable i.e. delegate and the same is returned which is saved in setNative variable inside timers.ts.
For complete workflow, you can refer below article.
https://medium.com/reverse-engineering-angular/angular-deep-dive-zone-js-how-does-it-monkey-patches-various-apis-9cc1c7fcc321