Thanks for chiming in
What I ended up doing was this: For every pipeline job I needed I created a freestyle job as the "trigger buddy" for the pipeline job. The pipeline job does not get any build triggers at all, while the "trigger buddy" has a combination of upstream dependencies and scm triggers that determine when the pipeline should run. As it is a freestyle job, you have a possibility to block it while its up/downstream dependencies are building. The only build step the trigger buddy has is to invoke the pipeline project and wait for its completion. It's a bit of an overhead to manage, but as long as pipelines do not have the blocking options I don't see an easier alternative.
Most of the time this approach works fine, but when the load on the Jenkins server became very high we've seen synchronization problems (Pipeline steps hanging or the trigger buddy waiting for the pipeline to finish while it already has), but it's probably unreasonable to expect Jenkins to cope with extreme situations and we managed to throttle the builds to the point where these problems disappeared.
If you are concerned about wasting resources because Jenkins tends to pick sub optimum paths through your dependency tree you might want to have a look at the Dependency Queue Plugin. The last maintained version seems incompatible with Jenkins 2.x, but if you go ahead and build the latest sources from github you'll get it working. It also helps to reduce the dependency tree as much as possible - I initially had ours reflect the source code dependencies one by one, but if you reduce it to only absolutely the necessary paths (e.g. you have 3 projects A, B and C; A triggers B and C and B triggers C then it's better to not list A in the upstream dependencies of C because A will implicitly trigger C anyway) then Jenkins will run through your build a lot smoother.