How to disable publish button if post title exists

This is something you could always do with the help of jQuery Ajax, and get_page_by_title('About', OBJECT, 'post') tool.

You basically listen to changes on the title field, check if at least 1 post already exists with same title, then enable the submit button if it doesn’t, otherwise keep it disabled as it is by default (on page load, the button gets disabled until further check).

add_action('wp_ajax_check-posts-by-title', function(){
    $title = isset( $_REQUEST['title'] ) ? esc_attr( $_REQUEST['title'] ) : null;
    // check for title
    if ( !$title ) {
        return wp_send_json(array(
            'enable_btn' => false,
            'message' => 'No title specified!' 
        ));
    }
    $post = get_page_by_title($title, OBJECT, 'post');
    // check for post
    if ( isset($post->ID) && 'publish' === $post->post_status ) {
        return wp_send_json(array(
            'enable_btn' => false
        ));
    }
    // nothing caught
    return wp_send_json(array(
        'enable_btn' => true
    ));
    // kill response
    wp_die();
});

add_action('admin_footer', function() { 
    global $pagenow;

    if ( !$pagenow || !in_array($pagenow, array( 'post-new.php' )) )
        return; // only enqueue when writing/editing posts
    ?>
    <script>
        jQuery(document).ready(function($){
            $(document).on("change", "#titlediv #title", function(e){
                var i = $(this)
                  , f = i.closest('form')
                  , t = i.val()
                  , b = $('input[name="publish"]', f).first();

                if ( self.xhr ) {
                    self.xhr.abort();
                } else {
                    var xhr;
                }

                if ( !b.length ) return;
                b.attr('disabled','disabled');

                if ( $.trim( t ) ) {
                    self.xhr = $.ajax({type: 'post', url: 'admin-ajax.php', data: {
                        action: 'check-posts-by-title',
                        title: t
                    }, success: function(res){
                        if ( res && res.enable_btn ) {
                            b.removeAttr('disabled');
                        } else {
                            if ( res.message ) {
                                alert(res.message);
                            }
                        }
                    }, error: function(){
                        i.trigger('change'); // roll over
                    }});
                }
            });
            $('#titlediv #title').trigger('change');
        });
    </script>
    <?php
});

Hope that helps.