I'd actually suggest a mix of push based and pull based. Use push based so that things probably show up quickly, then do a pull and global state reconcilliation every N seconds or few minutes in order to make sure things don't get too out of sync if a push gets lost for some reason (And help detect when modedls don't match up).
Service Router implements both pull based and push based (although currently they are mutually exclusive). The push based bits inside of it use push based around Marathon's older "event bus" rather than the newer "event stream" (
http://mesosphere.github.io/marathon/docs/rest-api.html#event-stream), the event stream adds some simplicity in management (It uses bi-directional communication rather than requiring explicit registration + de-registration of a host which knows its own address / identity)
Push vs. pull is definitely a tradeoff, both in terms of latency of things showing up, as well as in the efficiency when operating at a large scale (Transferring 10,000 tasks json definition is much larger than sending a single "added task foo", "lost task bar"). Pulling is a bit easier to implement as a v1. With push you really need to be certain you reconcile periodically, since if your service has a different perspective than marathon (Do to implementation bugs in either, or inconsistencies which could occur due to various failures), things can get out of whack without noticing.